home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / DB / common.php < prev    next >
Encoding:
PHP Script  |  2005-07-07  |  67.9 KB  |  2,158 lines

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * Contains the DB_common base class
  7.  *
  8.  * PHP versions 4 and 5
  9.  *
  10.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  11.  * that is available through the world-wide-web at the following URI:
  12.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  13.  * the PHP License and are unable to obtain it through the web, please
  14.  * send a note to license@php.net so we can mail you a copy immediately.
  15.  *
  16.  * @category   Database
  17.  * @package    DB
  18.  * @author     Stig Bakken <ssb@php.net>
  19.  * @author     Tomas V.V. Cox <cox@idecnet.com>
  20.  * @author     Daniel Convissor <danielc@php.net>
  21.  * @copyright  1997-2005 The PHP Group
  22.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  23.  * @version    CVS: $Id: common.php,v 1.137 2005/04/07 14:27:35 danielc Exp $
  24.  * @link       http://pear.php.net/package/DB
  25.  */
  26.  
  27. /**
  28.  * Obtain the PEAR class so it can be extended from
  29.  */
  30. require_once 'PEAR.php';
  31.  
  32. /**
  33.  * DB_common is the base class from which each database driver class extends
  34.  *
  35.  * All common methods are declared here.  If a given DBMS driver contains
  36.  * a particular method, that method will overload the one here.
  37.  *
  38.  * @category   Database
  39.  * @package    DB
  40.  * @author     Stig Bakken <ssb@php.net>
  41.  * @author     Tomas V.V. Cox <cox@idecnet.com>
  42.  * @author     Daniel Convissor <danielc@php.net>
  43.  * @copyright  1997-2005 The PHP Group
  44.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  45.  * @version    Release: 1.7.6
  46.  * @link       http://pear.php.net/package/DB
  47.  */
  48. class DB_common extends PEAR
  49. {
  50.     // {{{ properties
  51.  
  52.     /**
  53.      * The current default fetch mode
  54.      * @var integer
  55.      */
  56.     var $fetchmode = DB_FETCHMODE_ORDERED;
  57.  
  58.     /**
  59.      * The name of the class into which results should be fetched when
  60.      * DB_FETCHMODE_OBJECT is in effect
  61.      *
  62.      * @var string
  63.      */
  64.     var $fetchmode_object_class = 'stdClass';
  65.  
  66.     /**
  67.      * Was a connection present when the object was serialized()?
  68.      * @var bool
  69.      * @see DB_common::__sleep(), DB_common::__wake()
  70.      */
  71.     var $was_connected = null;
  72.  
  73.     /**
  74.      * The most recently executed query
  75.      * @var string
  76.      */
  77.     var $last_query = '';
  78.  
  79.     /**
  80.      * Run-time configuration options
  81.      *
  82.      * The 'optimize' option has been deprecated.  Use the 'portability'
  83.      * option instead.
  84.      *
  85.      * @var array
  86.      * @see DB_common::setOption()
  87.      */
  88.     var $options = array(
  89.         'result_buffering' => 500,
  90.         'persistent' => false,
  91.         'ssl' => false,
  92.         'debug' => 0,
  93.         'seqname_format' => '%s_seq',
  94.         'autofree' => false,
  95.         'portability' => DB_PORTABILITY_NONE,
  96.         'optimize' => 'performance',  // Deprecated.  Use 'portability'.
  97.     );
  98.  
  99.     /**
  100.      * The parameters from the most recently executed query
  101.      * @var array
  102.      * @since Property available since Release 1.7.0
  103.      */
  104.     var $last_parameters = array();
  105.  
  106.     /**
  107.      * The elements from each prepared statement
  108.      * @var array
  109.      */
  110.     var $prepare_tokens = array();
  111.  
  112.     /**
  113.      * The data types of the various elements in each prepared statement
  114.      * @var array
  115.      */
  116.     var $prepare_types = array();
  117.  
  118.     /**
  119.      * The prepared queries
  120.      * @var array
  121.      */
  122.     var $prepared_queries = array();
  123.  
  124.  
  125.     // }}}
  126.     // {{{ DB_common
  127.  
  128.     /**
  129.      * This constructor calls <kbd>$this->PEAR('DB_Error')</kbd>
  130.      *
  131.      * @return void
  132.      */
  133.     function DB_common()
  134.     {
  135.         $this->PEAR('DB_Error');
  136.     }
  137.  
  138.     // }}}
  139.     // {{{ __sleep()
  140.  
  141.     /**
  142.      * Automatically indicates which properties should be saved
  143.      * when PHP's serialize() function is called
  144.      *
  145.      * @return array  the array of properties names that should be saved
  146.      */
  147.     function __sleep()
  148.     {
  149.         if ($this->connection) {
  150.             // Don't disconnect(), people use serialize() for many reasons
  151.             $this->was_connected = true;
  152.         } else {
  153.             $this->was_connected = false;
  154.         }
  155.         if (isset($this->autocommit)) {
  156.             return array('autocommit',
  157.                          'dbsyntax',
  158.                          'dsn',
  159.                          'features',
  160.                          'fetchmode',
  161.                          'fetchmode_object_class',
  162.                          'options',
  163.                          'was_connected',
  164.                    );
  165.         } else {
  166.             return array('dbsyntax',
  167.                          'dsn',
  168.                          'features',
  169.                          'fetchmode',
  170.                          'fetchmode_object_class',
  171.                          'options',
  172.                          'was_connected',
  173.                    );
  174.         }
  175.     }
  176.  
  177.     // }}}
  178.     // {{{ __wakeup()
  179.  
  180.     /**
  181.      * Automatically reconnects to the database when PHP's unserialize()
  182.      * function is called
  183.      *
  184.      * The reconnection attempt is only performed if the object was connected
  185.      * at the time PHP's serialize() function was run.
  186.      *
  187.      * @return void
  188.      */
  189.     function __wakeup()
  190.     {
  191.         if ($this->was_connected) {
  192.             $this->connect($this->dsn, $this->options);
  193.         }
  194.     }
  195.  
  196.     // }}}
  197.     // {{{ __toString()
  198.  
  199.     /**
  200.      * Automatic string conversion for PHP 5
  201.      *
  202.      * @return string  a string describing the current PEAR DB object
  203.      *
  204.      * @since Method available since Release 1.7.0
  205.      */
  206.     function __toString()
  207.     {
  208.         $info = strtolower(get_class($this));
  209.         $info .=  ': (phptype=' . $this->phptype .
  210.                   ', dbsyntax=' . $this->dbsyntax .
  211.                   ')';
  212.         if ($this->connection) {
  213.             $info .= ' [connected]';
  214.         }
  215.         return $info;
  216.     }
  217.  
  218.     // }}}
  219.     // {{{ toString()
  220.  
  221.     /**
  222.      * DEPRECATED:  String conversion method
  223.      *
  224.      * @return string  a string describing the current PEAR DB object
  225.      *
  226.      * @deprecated Method deprecated in Release 1.7.0
  227.      */
  228.     function toString()
  229.     {
  230.         return $this->__toString();
  231.     }
  232.  
  233.     // }}}
  234.     // {{{ quoteString()
  235.  
  236.     /**
  237.      * DEPRECATED: Quotes a string so it can be safely used within string
  238.      * delimiters in a query
  239.      *
  240.      * @param string $string  the string to be quoted
  241.      *
  242.      * @return string  the quoted string
  243.      *
  244.      * @see DB_common::quoteSmart(), DB_common::escapeSimple()
  245.      * @deprecated Method deprecated some time before Release 1.2
  246.      */
  247.     function quoteString($string)
  248.     {
  249.         $string = $this->quote($string);
  250.         if ($string{0} == "'") {
  251.             return substr($string, 1, -1);
  252.         }
  253.         return $string;
  254.     }
  255.  
  256.     // }}}
  257.     // {{{ quote()
  258.  
  259.     /**
  260.      * DEPRECATED: Quotes a string so it can be safely used in a query
  261.      *
  262.      * @param string $string  the string to quote
  263.      *
  264.      * @return string  the quoted string or the string <samp>NULL</samp>
  265.      *                  if the value submitted is <kbd>null</kbd>.
  266.      *
  267.      * @see DB_common::quoteSmart(), DB_common::escapeSimple()
  268.      * @deprecated Deprecated in release 1.6.0
  269.      */
  270.     function quote($string = null)
  271.     {
  272.         return ($string === null) ? 'NULL'
  273.                                   : "'" . str_replace("'", "''", $string) . "'";
  274.     }
  275.  
  276.     // }}}
  277.     // {{{ quoteIdentifier()
  278.  
  279.     /**
  280.      * Quotes a string so it can be safely used as a table or column name
  281.      *
  282.      * Delimiting style depends on which database driver is being used.
  283.      *
  284.      * NOTE: just because you CAN use delimited identifiers doesn't mean
  285.      * you SHOULD use them.  In general, they end up causing way more
  286.      * problems than they solve.
  287.      *
  288.      * Portability is broken by using the following characters inside
  289.      * delimited identifiers:
  290.      *   + backtick (<kbd>`</kbd>) -- due to MySQL
  291.      *   + double quote (<kbd>"</kbd>) -- due to Oracle
  292.      *   + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
  293.      *
  294.      * Delimited identifiers are known to generally work correctly under
  295.      * the following drivers:
  296.      *   + mssql
  297.      *   + mysql
  298.      *   + mysqli
  299.      *   + oci8
  300.      *   + odbc(access)
  301.      *   + odbc(db2)
  302.      *   + pgsql
  303.      *   + sqlite
  304.      *   + sybase (must execute <kbd>set quoted_identifier on</kbd> sometime
  305.      *     prior to use)
  306.      *
  307.      * InterBase doesn't seem to be able to use delimited identifiers
  308.      * via PHP 4.  They work fine under PHP 5.
  309.      *
  310.      * @param string $str  the identifier name to be quoted
  311.      *
  312.      * @return string  the quoted identifier
  313.      *
  314.      * @since Method available since Release 1.6.0
  315.      */
  316.     function quoteIdentifier($str)
  317.     {
  318.         return '"' . str_replace('"', '""', $str) . '"';
  319.     }
  320.  
  321.     // }}}
  322.     // {{{ quoteSmart()
  323.  
  324.     /**
  325.      * Formats input so it can be safely used in a query
  326.      *
  327.      * The output depends on the PHP data type of input and the database
  328.      * type being used.
  329.      *
  330.      * @param mixed $in  the data to be formatted
  331.      *
  332.      * @return mixed  the formatted data.  The format depends on the input's
  333.      *                 PHP type:
  334.      * <ul>
  335.      *  <li>
  336.      *    <kbd>input</kbd> -> <samp>returns</samp>
  337.      *  </li>
  338.      *  <li>
  339.      *    <kbd>null</kbd> -> the string <samp>NULL</samp>
  340.      *  </li>
  341.      *  <li>
  342.      *    <kbd>integer</kbd> or <kbd>double</kbd> -> the unquoted number
  343.      *  </li>
  344.      *  <li>
  345.      *    <kbd>bool</kbd> -> output depends on the driver in use
  346.      *    Most drivers return integers: <samp>1</samp> if
  347.      *    <kbd>true</kbd> or <samp>0</samp> if
  348.      *    <kbd>false</kbd>.
  349.      *    Some return strings: <samp>TRUE</samp> if
  350.      *    <kbd>true</kbd> or <samp>FALSE</samp> if
  351.      *    <kbd>false</kbd>.
  352.      *    Finally one returns strings: <samp>T</samp> if
  353.      *    <kbd>true</kbd> or <samp>F</samp> if
  354.      *    <kbd>false</kbd>. Here is a list of each DBMS,
  355.      *    the values returned and the suggested column type:
  356.      *    <ul>
  357.      *      <li>
  358.      *        <kbd>dbase</kbd> -> <samp>T/F</samp>
  359.      *        (<kbd>Logical</kbd>)
  360.      *      </li>
  361.      *      <li>
  362.      *        <kbd>fbase</kbd> -> <samp>TRUE/FALSE</samp>
  363.      *        (<kbd>BOOLEAN</kbd>)
  364.      *      </li>
  365.      *      <li>
  366.      *        <kbd>ibase</kbd> -> <samp>1/0</samp>
  367.      *        (<kbd>SMALLINT</kbd>) [1]
  368.      *      </li>
  369.      *      <li>
  370.      *        <kbd>ifx</kbd> -> <samp>1/0</samp>
  371.      *        (<kbd>SMALLINT</kbd>) [1]
  372.      *      </li>
  373.      *      <li>
  374.      *        <kbd>msql</kbd> -> <samp>1/0</samp>
  375.      *        (<kbd>INTEGER</kbd>)
  376.      *      </li>
  377.      *      <li>
  378.      *        <kbd>mssql</kbd> -> <samp>1/0</samp>
  379.      *        (<kbd>BIT</kbd>)
  380.      *      </li>
  381.      *      <li>
  382.      *        <kbd>mysql</kbd> -> <samp>1/0</samp>
  383.      *        (<kbd>TINYINT(1)</kbd>)
  384.      *      </li>
  385.      *      <li>
  386.      *        <kbd>mysqli</kbd> -> <samp>1/0</samp>
  387.      *        (<kbd>TINYINT(1)</kbd>)
  388.      *      </li>
  389.      *      <li>
  390.      *        <kbd>oci8</kbd> -> <samp>1/0</samp>
  391.      *        (<kbd>NUMBER(1)</kbd>)
  392.      *      </li>
  393.      *      <li>
  394.      *        <kbd>odbc</kbd> -> <samp>1/0</samp>
  395.      *        (<kbd>SMALLINT</kbd>) [1]
  396.      *      </li>
  397.      *      <li>
  398.      *        <kbd>pgsql</kbd> -> <samp>TRUE/FALSE</samp>
  399.      *        (<kbd>BOOLEAN</kbd>)
  400.      *      </li>
  401.      *      <li>
  402.      *        <kbd>sqlite</kbd> -> <samp>1/0</samp>
  403.      *        (<kbd>INTEGER</kbd>)
  404.      *      </li>
  405.      *      <li>
  406.      *        <kbd>sybase</kbd> -> <samp>1/0</samp>
  407.      *        (<kbd>TINYINT(1)</kbd>)
  408.      *      </li>
  409.      *    </ul>
  410.      *    [1] Accommodate the lowest common denominator because not all
  411.      *    versions of have <kbd>BOOLEAN</kbd>.
  412.      *  </li>
  413.      *  <li>
  414.      *    other (including strings and numeric strings) ->
  415.      *    the data with single quotes escaped by preceeding
  416.      *    single quotes, backslashes are escaped by preceeding
  417.      *    backslashes, then the whole string is encapsulated
  418.      *    between single quotes
  419.      *  </li>
  420.      * </ul>
  421.      *
  422.      * @see DB_common::escapeSimple()
  423.      * @since Method available since Release 1.6.0
  424.      */
  425.     function quoteSmart($in)
  426.     {
  427.         if (is_int($in) || is_double($in)) {
  428.             return $in;
  429.         } elseif (is_bool($in)) {
  430.             return $in ? 1 : 0;
  431.         } elseif (is_null($in)) {
  432.             return 'NULL';
  433.         } else {
  434.             return "'" . $this->escapeSimple($in) . "'";
  435.         }
  436.     }
  437.  
  438.     // }}}
  439.     // {{{ escapeSimple()
  440.  
  441.     /**
  442.      * Escapes a string according to the current DBMS's standards
  443.      *
  444.      * In SQLite, this makes things safe for inserts/updates, but may
  445.      * cause problems when performing text comparisons against columns
  446.      * containing binary data. See the
  447.      * {@link http://php.net/sqlite_escape_string PHP manual} for more info.
  448.      *
  449.      * @param string $str  the string to be escaped
  450.      *
  451.      * @return string  the escaped string
  452.      *
  453.      * @see DB_common::quoteSmart()
  454.      * @since Method available since Release 1.6.0
  455.      */
  456.     function escapeSimple($str)
  457.     {
  458.         return str_replace("'", "''", $str);
  459.     }
  460.  
  461.     // }}}
  462.     // {{{ provides()
  463.  
  464.     /**
  465.      * Tells whether the present driver supports a given feature
  466.      *
  467.      * @param string $feature  the feature you're curious about
  468.      *
  469.      * @return bool  whether this driver supports $feature
  470.      */
  471.     function provides($feature)
  472.     {
  473.         return $this->features[$feature];
  474.     }
  475.  
  476.     // }}}
  477.     // {{{ setFetchMode()
  478.  
  479.     /**
  480.      * Sets the fetch mode that should be used by default for query results
  481.      *
  482.      * @param integer $fetchmode    DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC
  483.      *                               or DB_FETCHMODE_OBJECT
  484.      * @param string $object_class  the class name of the object to be returned
  485.      *                               by the fetch methods when the
  486.      *                               DB_FETCHMODE_OBJECT mode is selected.
  487.      *                               If no class is specified by default a cast
  488.      *                               to object from the assoc array row will be
  489.      *                               done.  There is also the posibility to use
  490.      *                               and extend the 'DB_row' class.
  491.      *
  492.      * @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT
  493.      */
  494.     function setFetchMode($fetchmode, $object_class = 'stdClass')
  495.     {
  496.         switch ($fetchmode) {
  497.             case DB_FETCHMODE_OBJECT:
  498.                 $this->fetchmode_object_class = $object_class;
  499.             case DB_FETCHMODE_ORDERED:
  500.             case DB_FETCHMODE_ASSOC:
  501.                 $this->fetchmode = $fetchmode;
  502.                 break;
  503.             default:
  504.                 return $this->raiseError('invalid fetchmode mode');
  505.         }
  506.     }
  507.  
  508.     // }}}
  509.     // {{{ setOption()
  510.  
  511.     /**
  512.      * Sets run-time configuration options for PEAR DB
  513.      *
  514.      * Options, their data types, default values and description:
  515.      * <ul>
  516.      * <li>
  517.      * <var>autofree</var> <kbd>boolean</kbd> = <samp>false</samp>
  518.      *      <br />should results be freed automatically when there are no
  519.      *            more rows?
  520.      * </li><li>
  521.      * <var>result_buffering</var> <kbd>integer</kbd> = <samp>500</samp>
  522.      *      <br />how many rows of the result set should be buffered?
  523.      *      <br />In mysql: mysql_unbuffered_query() is used instead of
  524.      *            mysql_query() if this value is 0.  (Release 1.7.0)
  525.      *      <br />In oci8: this value is passed to ocisetprefetch().
  526.      *            (Release 1.7.0)
  527.      * </li><li>
  528.      * <var>debug</var> <kbd>integer</kbd> = <samp>0</samp>
  529.      *      <br />debug level
  530.      * </li><li>
  531.      * <var>persistent</var> <kbd>boolean</kbd> = <samp>false</samp>
  532.      *      <br />should the connection be persistent?
  533.      * </li><li>
  534.      * <var>portability</var> <kbd>integer</kbd> = <samp>DB_PORTABILITY_NONE</samp>
  535.      *      <br />portability mode constant (see below)
  536.      * </li><li>
  537.      * <var>seqname_format</var> <kbd>string</kbd> = <samp>%s_seq</samp>
  538.      *      <br />the sprintf() format string used on sequence names.  This
  539.      *            format is applied to sequence names passed to
  540.      *            createSequence(), nextID() and dropSequence().
  541.      * </li><li>
  542.      * <var>ssl</var> <kbd>boolean</kbd> = <samp>false</samp>
  543.      *      <br />use ssl to connect?
  544.      * </li>
  545.      * </ul>
  546.      *
  547.      * -----------------------------------------
  548.      *
  549.      * PORTABILITY MODES
  550.      *
  551.      * These modes are bitwised, so they can be combined using <kbd>|</kbd>
  552.      * and removed using <kbd>^</kbd>.  See the examples section below on how
  553.      * to do this.
  554.      *
  555.      * <samp>DB_PORTABILITY_NONE</samp>
  556.      * turn off all portability features
  557.      *
  558.      * This mode gets automatically turned on if the deprecated
  559.      * <var>optimize</var> option gets set to <samp>performance</samp>.
  560.      *
  561.      *
  562.      * <samp>DB_PORTABILITY_LOWERCASE</samp>
  563.      * convert names of tables and fields to lower case when using
  564.      * <kbd>get*()</kbd>, <kbd>fetch*()</kbd> and <kbd>tableInfo()</kbd>
  565.      *
  566.      * This mode gets automatically turned on in the following databases
  567.      * if the deprecated option <var>optimize</var> gets set to
  568.      * <samp>portability</samp>:
  569.      * + oci8
  570.      *
  571.      *
  572.      * <samp>DB_PORTABILITY_RTRIM</samp>
  573.      * right trim the data output by <kbd>get*()</kbd> <kbd>fetch*()</kbd>
  574.      *
  575.      *
  576.      * <samp>DB_PORTABILITY_DELETE_COUNT</samp>
  577.      * force reporting the number of rows deleted
  578.      *
  579.      * Some DBMS's don't count the number of rows deleted when performing
  580.      * simple <kbd>DELETE FROM tablename</kbd> queries.  This portability
  581.      * mode tricks such DBMS's into telling the count by adding
  582.      * <samp>WHERE 1=1</samp> to the end of <kbd>DELETE</kbd> queries.
  583.      *
  584.      * This mode gets automatically turned on in the following databases
  585.      * if the deprecated option <var>optimize</var> gets set to
  586.      * <samp>portability</samp>:
  587.      * + fbsql
  588.      * + mysql
  589.      * + mysqli
  590.      * + sqlite
  591.      *
  592.      *
  593.      * <samp>DB_PORTABILITY_NUMROWS</samp>
  594.      * enable hack that makes <kbd>numRows()</kbd> work in Oracle
  595.      *
  596.      * This mode gets automatically turned on in the following databases
  597.      * if the deprecated option <var>optimize</var> gets set to
  598.      * <samp>portability</samp>:
  599.      * + oci8
  600.      *
  601.      *
  602.      * <samp>DB_PORTABILITY_ERRORS</samp>
  603.      * makes certain error messages in certain drivers compatible
  604.      * with those from other DBMS's
  605.      *
  606.      * + mysql, mysqli:  change unique/primary key constraints
  607.      *   DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
  608.      *
  609.      * + odbc(access):  MS's ODBC driver reports 'no such field' as code
  610.      *   07001, which means 'too few parameters.'  When this option is on
  611.      *   that code gets mapped to DB_ERROR_NOSUCHFIELD.
  612.      *   DB_ERROR_MISMATCH -> DB_ERROR_NOSUCHFIELD
  613.      *
  614.      * <samp>DB_PORTABILITY_NULL_TO_EMPTY</samp>
  615.      * convert null values to empty strings in data output by get*() and
  616.      * fetch*().  Needed because Oracle considers empty strings to be null,
  617.      * while most other DBMS's know the difference between empty and null.
  618.      *
  619.      *
  620.      * <samp>DB_PORTABILITY_ALL</samp>
  621.      * turn on all portability features
  622.      *
  623.      * -----------------------------------------
  624.      *
  625.      * Example 1. Simple setOption() example
  626.      * <code>
  627.      * $db->setOption('autofree', true);
  628.      * </code>
  629.      *
  630.      * Example 2. Portability for lowercasing and trimming
  631.      * <code>
  632.      * $db->setOption('portability',
  633.      *                 DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_RTRIM);
  634.      * </code>
  635.      *
  636.      * Example 3. All portability options except trimming
  637.      * <code>
  638.      * $db->setOption('portability',
  639.      *                 DB_PORTABILITY_ALL ^ DB_PORTABILITY_RTRIM);
  640.      * </code>
  641.      *
  642.      * @param string $option option name
  643.      * @param mixed  $value value for the option
  644.      *
  645.      * @return int  DB_OK on success.  A DB_Error object on failure.
  646.      *
  647.      * @see DB_common::$options
  648.      */
  649.     function setOption($option, $value)
  650.     {
  651.         if (isset($this->options[$option])) {
  652.             $this->options[$option] = $value;
  653.  
  654.             /*
  655.              * Backwards compatibility check for the deprecated 'optimize'
  656.              * option.  Done here in case settings change after connecting.
  657.              */
  658.             if ($option == 'optimize') {
  659.                 if ($value == 'portability') {
  660.                     switch ($this->phptype) {
  661.                         case 'oci8':
  662.                             $this->options['portability'] =
  663.                                     DB_PORTABILITY_LOWERCASE |
  664.                                     DB_PORTABILITY_NUMROWS;
  665.                             break;
  666.                         case 'fbsql':
  667.                         case 'mysql':
  668.                         case 'mysqli':
  669.                         case 'sqlite':
  670.                             $this->options['portability'] =
  671.                                     DB_PORTABILITY_DELETE_COUNT;
  672.                             break;
  673.                     }
  674.                 } else {
  675.                     $this->options['portability'] = DB_PORTABILITY_NONE;
  676.                 }
  677.             }
  678.  
  679.             return DB_OK;
  680.         }
  681.         return $this->raiseError("unknown option $option");
  682.     }
  683.  
  684.     // }}}
  685.     // {{{ getOption()
  686.  
  687.     /**
  688.      * Returns the value of an option
  689.      *
  690.      * @param string $option  the option name you're curious about
  691.      *
  692.      * @return mixed  the option's value
  693.      */
  694.     function getOption($option)
  695.     {
  696.         if (isset($this->options[$option])) {
  697.             return $this->options[$option];
  698.         }
  699.         return $this->raiseError("unknown option $option");
  700.     }
  701.  
  702.     // }}}
  703.     // {{{ prepare()
  704.  
  705.     /**
  706.      * Prepares a query for multiple execution with execute()
  707.      *
  708.      * Creates a query that can be run multiple times.  Each time it is run,
  709.      * the placeholders, if any, will be replaced by the contents of
  710.      * execute()'s $data argument.
  711.      *
  712.      * Three types of placeholders can be used:
  713.      *   + <kbd>?</kbd>  scalar value (i.e. strings, integers).  The system
  714.      *                   will automatically quote and escape the data.
  715.      *   + <kbd>!</kbd>  value is inserted 'as is'
  716.      *   + <kbd>&</kbd>  requires a file name.  The file's contents get
  717.      *                   inserted into the query (i.e. saving binary
  718.      *                   data in a db)
  719.      *
  720.      * Example 1.
  721.      * <code>
  722.      * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)');
  723.      * $data = array(
  724.      *     "John's text",
  725.      *     "'it''s good'",
  726.      *     'filename.txt'
  727.      * );
  728.      * $res = $db->execute($sth, $data);
  729.      * </code>
  730.      *
  731.      * Use backslashes to escape placeholder characters if you don't want
  732.      * them to be interpreted as placeholders:
  733.      * <pre>
  734.      *    "UPDATE foo SET col=? WHERE col='over \& under'"
  735.      * </pre>
  736.      *
  737.      * With some database backends, this is emulated.
  738.      *
  739.      * {@internal ibase and oci8 have their own prepare() methods.}}
  740.      *
  741.      * @param string $query  the query to be prepared
  742.      *
  743.      * @return mixed  DB statement resource on success. A DB_Error object
  744.      *                 on failure.
  745.      *
  746.      * @see DB_common::execute()
  747.      */
  748.     function prepare($query)
  749.     {
  750.         $tokens   = preg_split('/((?<!\\\)[&?!])/', $query, -1,
  751.                                PREG_SPLIT_DELIM_CAPTURE);
  752.         $token     = 0;
  753.         $types     = array();
  754.         $newtokens = array();
  755.  
  756.         foreach ($tokens as $val) {
  757.             switch ($val) {
  758.                 case '?':
  759.                     $types[$token++] = DB_PARAM_SCALAR;
  760.                     break;
  761.                 case '&':
  762.                     $types[$token++] = DB_PARAM_OPAQUE;
  763.                     break;
  764.                 case '!':
  765.                     $types[$token++] = DB_PARAM_MISC;
  766.                     break;
  767.                 default:
  768.                     $newtokens[] = preg_replace('/\\\([&?!])/', "\\1", $val);
  769.             }
  770.         }
  771.  
  772.         $this->prepare_tokens[] = &$newtokens;
  773.         end($this->prepare_tokens);
  774.  
  775.         $k = key($this->prepare_tokens);
  776.         $this->prepare_types[$k] = $types;
  777.         $this->prepared_queries[$k] = implode(' ', $newtokens);
  778.  
  779.         return $k;
  780.     }
  781.  
  782.     // }}}
  783.     // {{{ autoPrepare()
  784.  
  785.     /**
  786.      * Automaticaly generates an insert or update query and pass it to prepare()
  787.      *
  788.      * @param string $table         the table name
  789.      * @param array  $table_fields  the array of field names
  790.      * @param int    $mode          a type of query to make:
  791.      *                               DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
  792.      * @param string $where         for update queries: the WHERE clause to
  793.      *                               append to the SQL statement.  Don't
  794.      *                               include the "WHERE" keyword.
  795.      *
  796.      * @return resource  the query handle
  797.      *
  798.      * @uses DB_common::prepare(), DB_common::buildManipSQL()
  799.      */
  800.     function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT,
  801.                          $where = false)
  802.     {
  803.         $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
  804.         if (DB::isError($query)) {
  805.             return $query;
  806.         }
  807.         return $this->prepare($query);
  808.     }
  809.  
  810.     // }}}
  811.     // {{{ autoExecute()
  812.  
  813.     /**
  814.      * Automaticaly generates an insert or update query and call prepare()
  815.      * and execute() with it
  816.      *
  817.      * @param string $table         the table name
  818.      * @param array  $fields_values the associative array where $key is a
  819.      *                               field name and $value its value
  820.      * @param int    $mode          a type of query to make:
  821.      *                               DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
  822.      * @param string $where         for update queries: the WHERE clause to
  823.      *                               append to the SQL statement.  Don't
  824.      *                               include the "WHERE" keyword.
  825.      *
  826.      * @return mixed  a new DB_result object for successful SELECT queries
  827.      *                 or DB_OK for successul data manipulation queries.
  828.      *                 A DB_Error object on failure.
  829.      *
  830.      * @uses DB_common::autoPrepare(), DB_common::execute()
  831.      */
  832.     function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT,
  833.                          $where = false)
  834.     {
  835.         $sth = $this->autoPrepare($table, array_keys($fields_values), $mode,
  836.                                   $where);
  837.         if (DB::isError($sth)) {
  838.             return $sth;
  839.         }
  840.         $ret =& $this->execute($sth, array_values($fields_values));
  841.         $this->freePrepared($sth);
  842.         return $ret;
  843.  
  844.     }
  845.  
  846.     // }}}
  847.     // {{{ buildManipSQL()
  848.  
  849.     /**
  850.      * Produces an SQL query string for autoPrepare()
  851.      *
  852.      * Example:
  853.      * <pre>
  854.      * buildManipSQL('table_sql', array('field1', 'field2', 'field3'),
  855.      *               DB_AUTOQUERY_INSERT);
  856.      * </pre>
  857.      *
  858.      * That returns
  859.      * <samp>
  860.      * INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?)
  861.      * </samp>
  862.      *
  863.      * NOTES:
  864.      *   - This belongs more to a SQL Builder class, but this is a simple
  865.      *     facility.
  866.      *   - Be carefull! If you don't give a $where param with an UPDATE
  867.      *     query, all the records of the table will be updated!
  868.      *
  869.      * @param string $table         the table name
  870.      * @param array  $table_fields  the array of field names
  871.      * @param int    $mode          a type of query to make:
  872.      *                               DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
  873.      * @param string $where         for update queries: the WHERE clause to
  874.      *                               append to the SQL statement.  Don't
  875.      *                               include the "WHERE" keyword.
  876.      *
  877.      * @return string  the sql query for autoPrepare()
  878.      */
  879.     function buildManipSQL($table, $table_fields, $mode, $where = false)
  880.     {
  881.         if (count($table_fields) == 0) {
  882.             return $this->raiseError(DB_ERROR_NEED_MORE_DATA);
  883.         }
  884.         $first = true;
  885.         switch ($mode) {
  886.             case DB_AUTOQUERY_INSERT:
  887.                 $values = '';
  888.                 $names = '';
  889.                 foreach ($table_fields as $value) {
  890.                     if ($first) {
  891.                         $first = false;
  892.                     } else {
  893.                         $names .= ',';
  894.                         $values .= ',';
  895.                     }
  896.                     $names .= $value;
  897.                     $values .= '?';
  898.                 }
  899.                 return "INSERT INTO $table ($names) VALUES ($values)";
  900.             case DB_AUTOQUERY_UPDATE:
  901.                 $set = '';
  902.                 foreach ($table_fields as $value) {
  903.                     if ($first) {
  904.                         $first = false;
  905.                     } else {
  906.                         $set .= ',';
  907.                     }
  908.                     $set .= "$value = ?";
  909.                 }
  910.                 $sql = "UPDATE $table SET $set";
  911.                 if ($where) {
  912.                     $sql .= " WHERE $where";
  913.                 }
  914.                 return $sql;
  915.             default:
  916.                 return $this->raiseError(DB_ERROR_SYNTAX);
  917.         }
  918.     }
  919.  
  920.     // }}}
  921.     // {{{ execute()
  922.  
  923.     /**
  924.      * Executes a DB statement prepared with prepare()
  925.      *
  926.      * Example 1.
  927.      * <code>
  928.      * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)');
  929.      * $data = array(
  930.      *     "John's text",
  931.      *     "'it''s good'",
  932.      *     'filename.txt'
  933.      * );
  934.      * $res =& $db->execute($sth, $data);
  935.      * </code>
  936.      *
  937.      * @param resource $stmt  a DB statement resource returned from prepare()
  938.      * @param mixed    $data  array, string or numeric data to be used in
  939.      *                         execution of the statement.  Quantity of items
  940.      *                         passed must match quantity of placeholders in
  941.      *                         query:  meaning 1 placeholder for non-array
  942.      *                         parameters or 1 placeholder per array element.
  943.      *
  944.      * @return mixed  a new DB_result object for successful SELECT queries
  945.      *                 or DB_OK for successul data manipulation queries.
  946.      *                 A DB_Error object on failure.
  947.      *
  948.      * {@internal ibase and oci8 have their own execute() methods.}}
  949.      *
  950.      * @see DB_common::prepare()
  951.      */
  952.     function &execute($stmt, $data = array())
  953.     {
  954.         $realquery = $this->executeEmulateQuery($stmt, $data);
  955.         if (DB::isError($realquery)) {
  956.             return $realquery;
  957.         }
  958.         $result = $this->simpleQuery($realquery);
  959.  
  960.         if ($result === DB_OK || DB::isError($result)) {
  961.             return $result;
  962.         } else {
  963.             $tmp =& new DB_result($this, $result);
  964.             return $tmp;
  965.         }
  966.     }
  967.  
  968.     // }}}
  969.     // {{{ executeEmulateQuery()
  970.  
  971.     /**
  972.      * Emulates executing prepared statements if the DBMS not support them
  973.      *
  974.      * @param resource $stmt  a DB statement resource returned from execute()
  975.      * @param mixed    $data  array, string or numeric data to be used in
  976.      *                         execution of the statement.  Quantity of items
  977.      *                         passed must match quantity of placeholders in
  978.      *                         query:  meaning 1 placeholder for non-array
  979.      *                         parameters or 1 placeholder per array element.
  980.      *
  981.      * @return mixed  a string containing the real query run when emulating
  982.      *                 prepare/execute.  A DB_Error object on failure.
  983.      *
  984.      * @access protected
  985.      * @see DB_common::execute()
  986.      */
  987.     function executeEmulateQuery($stmt, $data = array())
  988.     {
  989.         $stmt = (int)$stmt;
  990.         $data = (array)$data;
  991.         $this->last_parameters = $data;
  992.  
  993.         if (count($this->prepare_types[$stmt]) != count($data)) {
  994.             $this->last_query = $this->prepared_queries[$stmt];
  995.             return $this->raiseError(DB_ERROR_MISMATCH);
  996.         }
  997.  
  998.         $realquery = $this->prepare_tokens[$stmt][0];
  999.  
  1000.         $i = 0;
  1001.         foreach ($data as $value) {
  1002.             if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) {
  1003.                 $realquery .= $this->quoteSmart($value);
  1004.             } elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) {
  1005.                 $fp = @fopen($value, 'rb');
  1006.                 if (!$fp) {
  1007.                     return $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
  1008.                 }
  1009.                 $realquery .= $this->quoteSmart(fread($fp, filesize($value)));
  1010.                 fclose($fp);
  1011.             } else {
  1012.                 $realquery .= $value;
  1013.             }
  1014.  
  1015.             $realquery .= $this->prepare_tokens[$stmt][++$i];
  1016.         }
  1017.  
  1018.         return $realquery;
  1019.     }
  1020.  
  1021.     // }}}
  1022.     // {{{ executeMultiple()
  1023.  
  1024.     /**
  1025.      * Performs several execute() calls on the same statement handle
  1026.      *
  1027.      * $data must be an array indexed numerically
  1028.      * from 0, one execute call is done for every "row" in the array.
  1029.      *
  1030.      * If an error occurs during execute(), executeMultiple() does not
  1031.      * execute the unfinished rows, but rather returns that error.
  1032.      *
  1033.      * @param resource $stmt  query handle from prepare()
  1034.      * @param array    $data  numeric array containing the
  1035.      *                         data to insert into the query
  1036.      *
  1037.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1038.      *
  1039.      * @see DB_common::prepare(), DB_common::execute()
  1040.      */
  1041.     function executeMultiple($stmt, $data)
  1042.     {
  1043.         foreach ($data as $value) {
  1044.             $res =& $this->execute($stmt, $value);
  1045.             if (DB::isError($res)) {
  1046.                 return $res;
  1047.             }
  1048.         }
  1049.         return DB_OK;
  1050.     }
  1051.  
  1052.     // }}}
  1053.     // {{{ freePrepared()
  1054.  
  1055.     /**
  1056.      * Frees the internal resources associated with a prepared query
  1057.      *
  1058.      * @param resource $stmt           the prepared statement's PHP resource
  1059.      * @param bool     $free_resource  should the PHP resource be freed too?
  1060.      *                                  Use false if you need to get data
  1061.      *                                  from the result set later.
  1062.      *
  1063.      * @return bool  TRUE on success, FALSE if $result is invalid
  1064.      *
  1065.      * @see DB_common::prepare()
  1066.      */
  1067.     function freePrepared($stmt, $free_resource = true)
  1068.     {
  1069.         $stmt = (int)$stmt;
  1070.         if (isset($this->prepare_tokens[$stmt])) {
  1071.             unset($this->prepare_tokens[$stmt]);
  1072.             unset($this->prepare_types[$stmt]);
  1073.             unset($this->prepared_queries[$stmt]);
  1074.             return true;
  1075.         }
  1076.         return false;
  1077.     }
  1078.  
  1079.     // }}}
  1080.     // {{{ modifyQuery()
  1081.  
  1082.     /**
  1083.      * Changes a query string for various DBMS specific reasons
  1084.      *
  1085.      * It is defined here to ensure all drivers have this method available.
  1086.      *
  1087.      * @param string $query  the query string to modify
  1088.      *
  1089.      * @return string  the modified query string
  1090.      *
  1091.      * @access protected
  1092.      * @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(),
  1093.      *      DB_sqlite::modifyQuery()
  1094.      */
  1095.     function modifyQuery($query)
  1096.     {
  1097.         return $query;
  1098.     }
  1099.  
  1100.     // }}}
  1101.     // {{{ modifyLimitQuery()
  1102.  
  1103.     /**
  1104.      * Adds LIMIT clauses to a query string according to current DBMS standards
  1105.      *
  1106.      * It is defined here to assure that all implementations
  1107.      * have this method defined.
  1108.      *
  1109.      * @param string $query   the query to modify
  1110.      * @param int    $from    the row to start to fetching (0 = the first row)
  1111.      * @param int    $count   the numbers of rows to fetch
  1112.      * @param mixed  $params  array, string or numeric data to be used in
  1113.      *                         execution of the statement.  Quantity of items
  1114.      *                         passed must match quantity of placeholders in
  1115.      *                         query:  meaning 1 placeholder for non-array
  1116.      *                         parameters or 1 placeholder per array element.
  1117.      *
  1118.      * @return string  the query string with LIMIT clauses added
  1119.      *
  1120.      * @access protected
  1121.      */
  1122.     function modifyLimitQuery($query, $from, $count, $params = array())
  1123.     {
  1124.         return $query;
  1125.     }
  1126.  
  1127.     // }}}
  1128.     // {{{ query()
  1129.  
  1130.     /**
  1131.      * Sends a query to the database server
  1132.      *
  1133.      * The query string can be either a normal statement to be sent directly
  1134.      * to the server OR if <var>$params</var> are passed the query can have
  1135.      * placeholders and it will be passed through prepare() and execute().
  1136.      *
  1137.      * @param string $query   the SQL query or the statement to prepare
  1138.      * @param mixed  $params  array, string or numeric data to be used in
  1139.      *                         execution of the statement.  Quantity of items
  1140.      *                         passed must match quantity of placeholders in
  1141.      *                         query:  meaning 1 placeholder for non-array
  1142.      *                         parameters or 1 placeholder per array element.
  1143.      *
  1144.      * @return mixed  a new DB_result object for successful SELECT queries
  1145.      *                 or DB_OK for successul data manipulation queries.
  1146.      *                 A DB_Error object on failure.
  1147.      *
  1148.      * @see DB_result, DB_common::prepare(), DB_common::execute()
  1149.      */
  1150.     function &query($query, $params = array())
  1151.     {
  1152.         if (sizeof($params) > 0) {
  1153.             $sth = $this->prepare($query);
  1154.             if (DB::isError($sth)) {
  1155.                 return $sth;
  1156.             }
  1157.             $ret =& $this->execute($sth, $params);
  1158.             $this->freePrepared($sth, false);
  1159.             return $ret;
  1160.         } else {
  1161.             $this->last_parameters = array();
  1162.             $result = $this->simpleQuery($query);
  1163.             if ($result === DB_OK || DB::isError($result)) {
  1164.                 return $result;
  1165.             } else {
  1166.                 $tmp =& new DB_result($this, $result);
  1167.                 return $tmp;
  1168.             }
  1169.         }
  1170.     }
  1171.  
  1172.     // }}}
  1173.     // {{{ limitQuery()
  1174.  
  1175.     /**
  1176.      * Generates and executes a LIMIT query
  1177.      *
  1178.      * @param string $query   the query
  1179.      * @param intr   $from    the row to start to fetching (0 = the first row)
  1180.      * @param int    $count   the numbers of rows to fetch
  1181.      * @param mixed  $params  array, string or numeric data to be used in
  1182.      *                         execution of the statement.  Quantity of items
  1183.      *                         passed must match quantity of placeholders in
  1184.      *                         query:  meaning 1 placeholder for non-array
  1185.      *                         parameters or 1 placeholder per array element.
  1186.      *
  1187.      * @return mixed  a new DB_result object for successful SELECT queries
  1188.      *                 or DB_OK for successul data manipulation queries.
  1189.      *                 A DB_Error object on failure.
  1190.      */
  1191.     function &limitQuery($query, $from, $count, $params = array())
  1192.     {
  1193.         $query = $this->modifyLimitQuery($query, $from, $count, $params);
  1194.         if (DB::isError($query)){
  1195.             return $query;
  1196.         }
  1197.         $result =& $this->query($query, $params);
  1198.         if (is_a($result, 'DB_result')) {
  1199.             $result->setOption('limit_from', $from);
  1200.             $result->setOption('limit_count', $count);
  1201.         }
  1202.         return $result;
  1203.     }
  1204.  
  1205.     // }}}
  1206.     // {{{ getOne()
  1207.  
  1208.     /**
  1209.      * Fetches the first column of the first row from a query result
  1210.      *
  1211.      * Takes care of doing the query and freeing the results when finished.
  1212.      *
  1213.      * @param string $query   the SQL query
  1214.      * @param mixed  $params  array, string or numeric data to be used in
  1215.      *                         execution of the statement.  Quantity of items
  1216.      *                         passed must match quantity of placeholders in
  1217.      *                         query:  meaning 1 placeholder for non-array
  1218.      *                         parameters or 1 placeholder per array element.
  1219.      *
  1220.      * @return mixed  the returned value of the query.
  1221.      *                 A DB_Error object on failure.
  1222.      */
  1223.     function &getOne($query, $params = array())
  1224.     {
  1225.         $params = (array)$params;
  1226.         // modifyLimitQuery() would be nice here, but it causes BC issues
  1227.         if (sizeof($params) > 0) {
  1228.             $sth = $this->prepare($query);
  1229.             if (DB::isError($sth)) {
  1230.                 return $sth;
  1231.             }
  1232.             $res =& $this->execute($sth, $params);
  1233.             $this->freePrepared($sth);
  1234.         } else {
  1235.             $res =& $this->query($query);
  1236.         }
  1237.  
  1238.         if (DB::isError($res)) {
  1239.             return $res;
  1240.         }
  1241.  
  1242.         $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED);
  1243.         $res->free();
  1244.  
  1245.         if ($err !== DB_OK) {
  1246.             return $err;
  1247.         }
  1248.  
  1249.         return $row[0];
  1250.     }
  1251.  
  1252.     // }}}
  1253.     // {{{ getRow()
  1254.  
  1255.     /**
  1256.      * Fetches the first row of data returned from a query result
  1257.      *
  1258.      * Takes care of doing the query and freeing the results when finished.
  1259.      *
  1260.      * @param string $query   the SQL query
  1261.      * @param mixed  $params  array, string or numeric data to be used in
  1262.      *                         execution of the statement.  Quantity of items
  1263.      *                         passed must match quantity of placeholders in
  1264.      *                         query:  meaning 1 placeholder for non-array
  1265.      *                         parameters or 1 placeholder per array element.
  1266.      * @param int $fetchmode  the fetch mode to use
  1267.      *
  1268.      * @return array  the first row of results as an array.
  1269.      *                 A DB_Error object on failure.
  1270.      */
  1271.     function &getRow($query, $params = array(),
  1272.                      $fetchmode = DB_FETCHMODE_DEFAULT)
  1273.     {
  1274.         // compat check, the params and fetchmode parameters used to
  1275.         // have the opposite order
  1276.         if (!is_array($params)) {
  1277.             if (is_array($fetchmode)) {
  1278.                 if ($params === null) {
  1279.                     $tmp = DB_FETCHMODE_DEFAULT;
  1280.                 } else {
  1281.                     $tmp = $params;
  1282.                 }
  1283.                 $params = $fetchmode;
  1284.                 $fetchmode = $tmp;
  1285.             } elseif ($params !== null) {
  1286.                 $fetchmode = $params;
  1287.                 $params = array();
  1288.             }
  1289.         }
  1290.         // modifyLimitQuery() would be nice here, but it causes BC issues
  1291.         if (sizeof($params) > 0) {
  1292.             $sth = $this->prepare($query);
  1293.             if (DB::isError($sth)) {
  1294.                 return $sth;
  1295.             }
  1296.             $res =& $this->execute($sth, $params);
  1297.             $this->freePrepared($sth);
  1298.         } else {
  1299.             $res =& $this->query($query);
  1300.         }
  1301.  
  1302.         if (DB::isError($res)) {
  1303.             return $res;
  1304.         }
  1305.  
  1306.         $err = $res->fetchInto($row, $fetchmode);
  1307.  
  1308.         $res->free();
  1309.  
  1310.         if ($err !== DB_OK) {
  1311.             return $err;
  1312.         }
  1313.  
  1314.         return $row;
  1315.     }
  1316.  
  1317.     // }}}
  1318.     // {{{ getCol()
  1319.  
  1320.     /**
  1321.      * Fetches a single column from a query result and returns it as an
  1322.      * indexed array
  1323.      *
  1324.      * @param string $query   the SQL query
  1325.      * @param mixed  $col     which column to return (integer [column number,
  1326.      *                         starting at 0] or string [column name])
  1327.      * @param mixed  $params  array, string or numeric data to be used in
  1328.      *                         execution of the statement.  Quantity of items
  1329.      *                         passed must match quantity of placeholders in
  1330.      *                         query:  meaning 1 placeholder for non-array
  1331.      *                         parameters or 1 placeholder per array element.
  1332.      *
  1333.      * @return array  the results as an array.  A DB_Error object on failure.
  1334.      *
  1335.      * @see DB_common::query()
  1336.      */
  1337.     function &getCol($query, $col = 0, $params = array())
  1338.     {
  1339.         $params = (array)$params;
  1340.         if (sizeof($params) > 0) {
  1341.             $sth = $this->prepare($query);
  1342.  
  1343.             if (DB::isError($sth)) {
  1344.                 return $sth;
  1345.             }
  1346.  
  1347.             $res =& $this->execute($sth, $params);
  1348.             $this->freePrepared($sth);
  1349.         } else {
  1350.             $res =& $this->query($query);
  1351.         }
  1352.  
  1353.         if (DB::isError($res)) {
  1354.             return $res;
  1355.         }
  1356.  
  1357.         $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC;
  1358.  
  1359.         if (!is_array($row = $res->fetchRow($fetchmode))) {
  1360.             $ret = array();
  1361.         } else {
  1362.             if (!array_key_exists($col, $row)) {
  1363.                 $ret =& $this->raiseError(DB_ERROR_NOSUCHFIELD);
  1364.             } else {
  1365.                 $ret = array($row[$col]);
  1366.                 while (is_array($row = $res->fetchRow($fetchmode))) {
  1367.                     $ret[] = $row[$col];
  1368.                 }
  1369.             }
  1370.         }
  1371.  
  1372.         $res->free();
  1373.  
  1374.         if (DB::isError($row)) {
  1375.             $ret = $row;
  1376.         }
  1377.  
  1378.         return $ret;
  1379.     }
  1380.  
  1381.     // }}}
  1382.     // {{{ getAssoc()
  1383.  
  1384.     /**
  1385.      * Fetches an entire query result and returns it as an
  1386.      * associative array using the first column as the key
  1387.      *
  1388.      * If the result set contains more than two columns, the value
  1389.      * will be an array of the values from column 2-n.  If the result
  1390.      * set contains only two columns, the returned value will be a
  1391.      * scalar with the value of the second column (unless forced to an
  1392.      * array with the $force_array parameter).  A DB error code is
  1393.      * returned on errors.  If the result set contains fewer than two
  1394.      * columns, a DB_ERROR_TRUNCATED error is returned.
  1395.      *
  1396.      * For example, if the table "mytable" contains:
  1397.      *
  1398.      * <pre>
  1399.      *  ID      TEXT       DATE
  1400.      * --------------------------------
  1401.      *  1       'one'      944679408
  1402.      *  2       'two'      944679408
  1403.      *  3       'three'    944679408
  1404.      * </pre>
  1405.      *
  1406.      * Then the call getAssoc('SELECT id,text FROM mytable') returns:
  1407.      * <pre>
  1408.      *   array(
  1409.      *     '1' => 'one',
  1410.      *     '2' => 'two',
  1411.      *     '3' => 'three',
  1412.      *   )
  1413.      * </pre>
  1414.      *
  1415.      * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
  1416.      * <pre>
  1417.      *   array(
  1418.      *     '1' => array('one', '944679408'),
  1419.      *     '2' => array('two', '944679408'),
  1420.      *     '3' => array('three', '944679408')
  1421.      *   )
  1422.      * </pre>
  1423.      *
  1424.      * If the more than one row occurs with the same value in the
  1425.      * first column, the last row overwrites all previous ones by
  1426.      * default.  Use the $group parameter if you don't want to
  1427.      * overwrite like this.  Example:
  1428.      *
  1429.      * <pre>
  1430.      * getAssoc('SELECT category,id,name FROM mytable', false, null,
  1431.      *          DB_FETCHMODE_ASSOC, true) returns:
  1432.      *
  1433.      *   array(
  1434.      *     '1' => array(array('id' => '4', 'name' => 'number four'),
  1435.      *                  array('id' => '6', 'name' => 'number six')
  1436.      *            ),
  1437.      *     '9' => array(array('id' => '4', 'name' => 'number four'),
  1438.      *                  array('id' => '6', 'name' => 'number six')
  1439.      *            )
  1440.      *   )
  1441.      * </pre>
  1442.      *
  1443.      * Keep in mind that database functions in PHP usually return string
  1444.      * values for results regardless of the database's internal type.
  1445.      *
  1446.      * @param string $query        the SQL query
  1447.      * @param bool   $force_array  used only when the query returns
  1448.      *                              exactly two columns.  If true, the values
  1449.      *                              of the returned array will be one-element
  1450.      *                              arrays instead of scalars.
  1451.      * @param mixed  $params       array, string or numeric data to be used in
  1452.      *                              execution of the statement.  Quantity of
  1453.      *                              items passed must match quantity of
  1454.      *                              placeholders in query:  meaning 1
  1455.      *                              placeholder for non-array parameters or
  1456.      *                              1 placeholder per array element.
  1457.      * @param int   $fetchmode     the fetch mode to use
  1458.      * @param bool  $group         if true, the values of the returned array
  1459.      *                              is wrapped in another array.  If the same
  1460.      *                              key value (in the first column) repeats
  1461.      *                              itself, the values will be appended to
  1462.      *                              this array instead of overwriting the
  1463.      *                              existing values.
  1464.      *
  1465.      * @return array  the associative array containing the query results.
  1466.      *                A DB_Error object on failure.
  1467.      */
  1468.     function &getAssoc($query, $force_array = false, $params = array(),
  1469.                        $fetchmode = DB_FETCHMODE_DEFAULT, $group = false)
  1470.     {
  1471.         $params = (array)$params;
  1472.         if (sizeof($params) > 0) {
  1473.             $sth = $this->prepare($query);
  1474.  
  1475.             if (DB::isError($sth)) {
  1476.                 return $sth;
  1477.             }
  1478.  
  1479.             $res =& $this->execute($sth, $params);
  1480.             $this->freePrepared($sth);
  1481.         } else {
  1482.             $res =& $this->query($query);
  1483.         }
  1484.  
  1485.         if (DB::isError($res)) {
  1486.             return $res;
  1487.         }
  1488.         if ($fetchmode == DB_FETCHMODE_DEFAULT) {
  1489.             $fetchmode = $this->fetchmode;
  1490.         }
  1491.         $cols = $res->numCols();
  1492.  
  1493.         if ($cols < 2) {
  1494.             $tmp =& $this->raiseError(DB_ERROR_TRUNCATED);
  1495.             return $tmp;
  1496.         }
  1497.  
  1498.         $results = array();
  1499.  
  1500.         if ($cols > 2 || $force_array) {
  1501.             // return array values
  1502.             // XXX this part can be optimized
  1503.             if ($fetchmode == DB_FETCHMODE_ASSOC) {
  1504.                 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) {
  1505.                     reset($row);
  1506.                     $key = current($row);
  1507.                     unset($row[key($row)]);
  1508.                     if ($group) {
  1509.                         $results[$key][] = $row;
  1510.                     } else {
  1511.                         $results[$key] = $row;
  1512.                     }
  1513.                 }
  1514.             } elseif ($fetchmode == DB_FETCHMODE_OBJECT) {
  1515.                 while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) {
  1516.                     $arr = get_object_vars($row);
  1517.                     $key = current($arr);
  1518.                     if ($group) {
  1519.                         $results[$key][] = $row;
  1520.                     } else {
  1521.                         $results[$key] = $row;
  1522.                     }
  1523.                 }
  1524.             } else {
  1525.                 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
  1526.                     // we shift away the first element to get
  1527.                     // indices running from 0 again
  1528.                     $key = array_shift($row);
  1529.                     if ($group) {
  1530.                         $results[$key][] = $row;
  1531.                     } else {
  1532.                         $results[$key] = $row;
  1533.                     }
  1534.                 }
  1535.             }
  1536.             if (DB::isError($row)) {
  1537.                 $results = $row;
  1538.             }
  1539.         } else {
  1540.             // return scalar values
  1541.             while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
  1542.                 if ($group) {
  1543.                     $results[$row[0]][] = $row[1];
  1544.                 } else {
  1545.                     $results[$row[0]] = $row[1];
  1546.                 }
  1547.             }
  1548.             if (DB::isError($row)) {
  1549.                 $results = $row;
  1550.             }
  1551.         }
  1552.  
  1553.         $res->free();
  1554.  
  1555.         return $results;
  1556.     }
  1557.  
  1558.     // }}}
  1559.     // {{{ getAll()
  1560.  
  1561.     /**
  1562.      * Fetches all of the rows from a query result
  1563.      *
  1564.      * @param string $query      the SQL query
  1565.      * @param mixed  $params     array, string or numeric data to be used in
  1566.      *                            execution of the statement.  Quantity of
  1567.      *                            items passed must match quantity of
  1568.      *                            placeholders in query:  meaning 1
  1569.      *                            placeholder for non-array parameters or
  1570.      *                            1 placeholder per array element.
  1571.      * @param int    $fetchmode  the fetch mode to use:
  1572.      *                            + DB_FETCHMODE_ORDERED
  1573.      *                            + DB_FETCHMODE_ASSOC
  1574.      *                            + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED
  1575.      *                            + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED
  1576.      *
  1577.      * @return array  the nested array.  A DB_Error object on failure.
  1578.      */
  1579.     function &getAll($query, $params = array(),
  1580.                      $fetchmode = DB_FETCHMODE_DEFAULT)
  1581.     {
  1582.         // compat check, the params and fetchmode parameters used to
  1583.         // have the opposite order
  1584.         if (!is_array($params)) {
  1585.             if (is_array($fetchmode)) {
  1586.                 if ($params === null) {
  1587.                     $tmp = DB_FETCHMODE_DEFAULT;
  1588.                 } else {
  1589.                     $tmp = $params;
  1590.                 }
  1591.                 $params = $fetchmode;
  1592.                 $fetchmode = $tmp;
  1593.             } elseif ($params !== null) {
  1594.                 $fetchmode = $params;
  1595.                 $params = array();
  1596.             }
  1597.         }
  1598.  
  1599.         if (sizeof($params) > 0) {
  1600.             $sth = $this->prepare($query);
  1601.  
  1602.             if (DB::isError($sth)) {
  1603.                 return $sth;
  1604.             }
  1605.  
  1606.             $res =& $this->execute($sth, $params);
  1607.             $this->freePrepared($sth);
  1608.         } else {
  1609.             $res =& $this->query($query);
  1610.         }
  1611.  
  1612.         if ($res === DB_OK || DB::isError($res)) {
  1613.             return $res;
  1614.         }
  1615.  
  1616.         $results = array();
  1617.         while (DB_OK === $res->fetchInto($row, $fetchmode)) {
  1618.             if ($fetchmode & DB_FETCHMODE_FLIPPED) {
  1619.                 foreach ($row as $key => $val) {
  1620.                     $results[$key][] = $val;
  1621.                 }
  1622.             } else {
  1623.                 $results[] = $row;
  1624.             }
  1625.         }
  1626.  
  1627.         $res->free();
  1628.  
  1629.         if (DB::isError($row)) {
  1630.             $tmp =& $this->raiseError($row);
  1631.             return $tmp;
  1632.         }
  1633.         return $results;
  1634.     }
  1635.  
  1636.     // }}}
  1637.     // {{{ autoCommit()
  1638.  
  1639.     /**
  1640.      * Enables or disables automatic commits
  1641.      *
  1642.      * @param bool $onoff  true turns it on, false turns it off
  1643.      *
  1644.      * @return int  DB_OK on success.  A DB_Error object if the driver
  1645.      *               doesn't support auto-committing transactions.
  1646.      */
  1647.     function autoCommit($onoff = false)
  1648.     {
  1649.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1650.     }
  1651.  
  1652.     // }}}
  1653.     // {{{ commit()
  1654.  
  1655.     /**
  1656.      * Commits the current transaction
  1657.      *
  1658.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1659.      */
  1660.     function commit()
  1661.     {
  1662.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1663.     }
  1664.  
  1665.     // }}}
  1666.     // {{{ rollback()
  1667.  
  1668.     /**
  1669.      * Reverts the current transaction
  1670.      *
  1671.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1672.      */
  1673.     function rollback()
  1674.     {
  1675.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1676.     }
  1677.  
  1678.     // }}}
  1679.     // {{{ numRows()
  1680.  
  1681.     /**
  1682.      * Determines the number of rows in a query result
  1683.      *
  1684.      * @param resource $result  the query result idenifier produced by PHP
  1685.      *
  1686.      * @return int  the number of rows.  A DB_Error object on failure.
  1687.      */
  1688.     function numRows($result)
  1689.     {
  1690.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1691.     }
  1692.  
  1693.     // }}}
  1694.     // {{{ affectedRows()
  1695.  
  1696.     /**
  1697.      * Determines the number of rows affected by a data maniuplation query
  1698.      *
  1699.      * 0 is returned for queries that don't manipulate data.
  1700.      *
  1701.      * @return int  the number of rows.  A DB_Error object on failure.
  1702.      */
  1703.     function affectedRows()
  1704.     {
  1705.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1706.     }
  1707.  
  1708.     // }}}
  1709.     // {{{ getSequenceName()
  1710.  
  1711.     /**
  1712.      * Generates the name used inside the database for a sequence
  1713.      *
  1714.      * The createSequence() docblock contains notes about storing sequence
  1715.      * names.
  1716.      *
  1717.      * @param string $sqn  the sequence's public name
  1718.      *
  1719.      * @return string  the sequence's name in the backend
  1720.      *
  1721.      * @access protected
  1722.      * @see DB_common::createSequence(), DB_common::dropSequence(),
  1723.      *      DB_common::nextID(), DB_common::setOption()
  1724.      */
  1725.     function getSequenceName($sqn)
  1726.     {
  1727.         return sprintf($this->getOption('seqname_format'),
  1728.                        preg_replace('/[^a-z0-9_.]/i', '_', $sqn));
  1729.     }
  1730.  
  1731.     // }}}
  1732.     // {{{ nextId()
  1733.  
  1734.     /**
  1735.      * Returns the next free id in a sequence
  1736.      *
  1737.      * @param string  $seq_name  name of the sequence
  1738.      * @param boolean $ondemand  when true, the seqence is automatically
  1739.      *                            created if it does not exist
  1740.      *
  1741.      * @return int  the next id number in the sequence.
  1742.      *               A DB_Error object on failure.
  1743.      *
  1744.      * @see DB_common::createSequence(), DB_common::dropSequence(),
  1745.      *      DB_common::getSequenceName()
  1746.      */
  1747.     function nextId($seq_name, $ondemand = true)
  1748.     {
  1749.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1750.     }
  1751.  
  1752.     // }}}
  1753.     // {{{ createSequence()
  1754.  
  1755.     /**
  1756.      * Creates a new sequence
  1757.      *
  1758.      * The name of a given sequence is determined by passing the string
  1759.      * provided in the <var>$seq_name</var> argument through PHP's sprintf()
  1760.      * function using the value from the <var>seqname_format</var> option as
  1761.      * the sprintf()'s format argument.
  1762.      *
  1763.      * <var>seqname_format</var> is set via setOption().
  1764.      *
  1765.      * @param string $seq_name  name of the new sequence
  1766.      *
  1767.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1768.      *
  1769.      * @see DB_common::dropSequence(), DB_common::getSequenceName(),
  1770.      *      DB_common::nextID()
  1771.      */
  1772.     function createSequence($seq_name)
  1773.     {
  1774.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1775.     }
  1776.  
  1777.     // }}}
  1778.     // {{{ dropSequence()
  1779.  
  1780.     /**
  1781.      * Deletes a sequence
  1782.      *
  1783.      * @param string $seq_name  name of the sequence to be deleted
  1784.      *
  1785.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1786.      *
  1787.      * @see DB_common::createSequence(), DB_common::getSequenceName(),
  1788.      *      DB_common::nextID()
  1789.      */
  1790.     function dropSequence($seq_name)
  1791.     {
  1792.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1793.     }
  1794.  
  1795.     // }}}
  1796.     // {{{ raiseError()
  1797.  
  1798.     /**
  1799.      * Communicates an error and invoke error callbacks, etc
  1800.      *
  1801.      * Basically a wrapper for PEAR::raiseError without the message string.
  1802.      *
  1803.      * @param mixed   integer error code, or a PEAR error object (all
  1804.      *                 other parameters are ignored if this parameter is
  1805.      *                 an object
  1806.      * @param int     error mode, see PEAR_Error docs
  1807.      * @param mixed   if error mode is PEAR_ERROR_TRIGGER, this is the
  1808.      *                 error level (E_USER_NOTICE etc).  If error mode is
  1809.      *                 PEAR_ERROR_CALLBACK, this is the callback function,
  1810.      *                 either as a function name, or as an array of an
  1811.      *                 object and method name.  For other error modes this
  1812.      *                 parameter is ignored.
  1813.      * @param string  extra debug information.  Defaults to the last
  1814.      *                 query and native error code.
  1815.      * @param mixed   native error code, integer or string depending the
  1816.      *                 backend
  1817.      *
  1818.      * @return object  the PEAR_Error object
  1819.      *
  1820.      * @see PEAR_Error
  1821.      */
  1822.     function &raiseError($code = DB_ERROR, $mode = null, $options = null,
  1823.                          $userinfo = null, $nativecode = null)
  1824.     {
  1825.         // The error is yet a DB error object
  1826.         if (is_object($code)) {
  1827.             // because we the static PEAR::raiseError, our global
  1828.             // handler should be used if it is set
  1829.             if ($mode === null && !empty($this->_default_error_mode)) {
  1830.                 $mode    = $this->_default_error_mode;
  1831.                 $options = $this->_default_error_options;
  1832.             }
  1833.             $tmp = PEAR::raiseError($code, null, $mode, $options,
  1834.                                     null, null, true);
  1835.             return $tmp;
  1836.         }
  1837.  
  1838.         if ($userinfo === null) {
  1839.             $userinfo = $this->last_query;
  1840.         }
  1841.  
  1842.         if ($nativecode) {
  1843.             $userinfo .= ' [nativecode=' . trim($nativecode) . ']';
  1844.         } else {
  1845.             $userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']';
  1846.         }
  1847.  
  1848.         $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo,
  1849.                                 'DB_Error', true);
  1850.         return $tmp;
  1851.     }
  1852.  
  1853.     // }}}
  1854.     // {{{ errorNative()
  1855.  
  1856.     /**
  1857.      * Gets the DBMS' native error code produced by the last query
  1858.      *
  1859.      * @return mixed  the DBMS' error code.  A DB_Error object on failure.
  1860.      */
  1861.     function errorNative()
  1862.     {
  1863.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1864.     }
  1865.  
  1866.     // }}}
  1867.     // {{{ errorCode()
  1868.  
  1869.     /**
  1870.      * Maps native error codes to DB's portable ones
  1871.      *
  1872.      * Uses the <var>$errorcode_map</var> property defined in each driver.
  1873.      *
  1874.      * @param string|int $nativecode  the error code returned by the DBMS
  1875.      *
  1876.      * @return int  the portable DB error code.  Return DB_ERROR if the
  1877.      *               current driver doesn't have a mapping for the
  1878.      *               $nativecode submitted.
  1879.      */
  1880.     function errorCode($nativecode)
  1881.     {
  1882.         if (isset($this->errorcode_map[$nativecode])) {
  1883.             return $this->errorcode_map[$nativecode];
  1884.         }
  1885.         // Fall back to DB_ERROR if there was no mapping.
  1886.         return DB_ERROR;
  1887.     }
  1888.  
  1889.     // }}}
  1890.     // {{{ errorMessage()
  1891.  
  1892.     /**
  1893.      * Maps a DB error code to a textual message
  1894.      *
  1895.      * @param integer $dbcode  the DB error code
  1896.      *
  1897.      * @return string  the error message corresponding to the error code
  1898.      *                  submitted.  FALSE if the error code is unknown.
  1899.      *
  1900.      * @see DB::errorMessage()
  1901.      */
  1902.     function errorMessage($dbcode)
  1903.     {
  1904.         return DB::errorMessage($this->errorcode_map[$dbcode]);
  1905.     }
  1906.  
  1907.     // }}}
  1908.     // {{{ tableInfo()
  1909.  
  1910.     /**
  1911.      * Returns information about a table or a result set
  1912.      *
  1913.      * The format of the resulting array depends on which <var>$mode</var>
  1914.      * you select.  The sample output below is based on this query:
  1915.      * <pre>
  1916.      *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
  1917.      *    FROM tblFoo
  1918.      *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
  1919.      * </pre>
  1920.      *
  1921.      * <ul>
  1922.      * <li>
  1923.      *
  1924.      * <kbd>null</kbd> (default)
  1925.      *   <pre>
  1926.      *   [0] => Array (
  1927.      *       [table] => tblFoo
  1928.      *       [name] => fldId
  1929.      *       [type] => int
  1930.      *       [len] => 11
  1931.      *       [flags] => primary_key not_null
  1932.      *   )
  1933.      *   [1] => Array (
  1934.      *       [table] => tblFoo
  1935.      *       [name] => fldPhone
  1936.      *       [type] => string
  1937.      *       [len] => 20
  1938.      *       [flags] =>
  1939.      *   )
  1940.      *   [2] => Array (
  1941.      *       [table] => tblBar
  1942.      *       [name] => fldId
  1943.      *       [type] => int
  1944.      *       [len] => 11
  1945.      *       [flags] => primary_key not_null
  1946.      *   )
  1947.      *   </pre>
  1948.      *
  1949.      * </li><li>
  1950.      *
  1951.      * <kbd>DB_TABLEINFO_ORDER</kbd>
  1952.      *
  1953.      *   <p>In addition to the information found in the default output,
  1954.      *   a notation of the number of columns is provided by the
  1955.      *   <samp>num_fields</samp> element while the <samp>order</samp>
  1956.      *   element provides an array with the column names as the keys and
  1957.      *   their location index number (corresponding to the keys in the
  1958.      *   the default output) as the values.</p>
  1959.      *
  1960.      *   <p>If a result set has identical field names, the last one is
  1961.      *   used.</p>
  1962.      *
  1963.      *   <pre>
  1964.      *   [num_fields] => 3
  1965.      *   [order] => Array (
  1966.      *       [fldId] => 2
  1967.      *       [fldTrans] => 1
  1968.      *   )
  1969.      *   </pre>
  1970.      *
  1971.      * </li><li>
  1972.      *
  1973.      * <kbd>DB_TABLEINFO_ORDERTABLE</kbd>
  1974.      *
  1975.      *   <p>Similar to <kbd>DB_TABLEINFO_ORDER</kbd> but adds more
  1976.      *   dimensions to the array in which the table names are keys and
  1977.      *   the field names are sub-keys.  This is helpful for queries that
  1978.      *   join tables which have identical field names.</p>
  1979.      *
  1980.      *   <pre>
  1981.      *   [num_fields] => 3
  1982.      *   [ordertable] => Array (
  1983.      *       [tblFoo] => Array (
  1984.      *           [fldId] => 0
  1985.      *           [fldPhone] => 1
  1986.      *       )
  1987.      *       [tblBar] => Array (
  1988.      *           [fldId] => 2
  1989.      *       )
  1990.      *   )
  1991.      *   </pre>
  1992.      *
  1993.      * </li>
  1994.      * </ul>
  1995.      *
  1996.      * The <samp>flags</samp> element contains a space separated list
  1997.      * of extra information about the field.  This data is inconsistent
  1998.      * between DBMS's due to the way each DBMS works.
  1999.      *   + <samp>primary_key</samp>
  2000.      *   + <samp>unique_key</samp>
  2001.      *   + <samp>multiple_key</samp>
  2002.      *   + <samp>not_null</samp>
  2003.      *
  2004.      * Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp>
  2005.      * elements if <var>$result</var> is a table name.  The following DBMS's
  2006.      * provide full information from queries:
  2007.      *   + fbsql
  2008.      *   + mysql
  2009.      *
  2010.      * If the 'portability' option has <samp>DB_PORTABILITY_LOWERCASE</samp>
  2011.      * turned on, the names of tables and fields will be lowercased.
  2012.      *
  2013.      * @param object|string  $result  DB_result object from a query or a
  2014.      *                                string containing the name of a table.
  2015.      *                                While this also accepts a query result
  2016.      *                                resource identifier, this behavior is
  2017.      *                                deprecated.
  2018.      * @param int  $mode   either unused or one of the tableInfo modes:
  2019.      *                     <kbd>DB_TABLEINFO_ORDERTABLE</kbd>,
  2020.      *                     <kbd>DB_TABLEINFO_ORDER</kbd> or
  2021.      *                     <kbd>DB_TABLEINFO_FULL</kbd> (which does both).
  2022.      *                     These are bitwise, so the first two can be
  2023.      *                     combined using <kbd>|</kbd>.
  2024.      *
  2025.      * @return array  an associative array with the information requested.
  2026.      *                 A DB_Error object on failure.
  2027.      *
  2028.      * @see DB_common::setOption()
  2029.      */
  2030.     function tableInfo($result, $mode = null)
  2031.     {
  2032.         /*
  2033.          * If the DB_<driver> class has a tableInfo() method, that one
  2034.          * overrides this one.  But, if the driver doesn't have one,
  2035.          * this method runs and tells users about that fact.
  2036.          */
  2037.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  2038.     }
  2039.  
  2040.     // }}}
  2041.     // {{{ getTables()
  2042.  
  2043.     /**
  2044.      * Lists the tables in the current database
  2045.      *
  2046.      * @return array  the list of tables.  A DB_Error object on failure.
  2047.      *
  2048.      * @deprecated Method deprecated some time before Release 1.2
  2049.      */
  2050.     function getTables()
  2051.     {
  2052.         return $this->getListOf('tables');
  2053.     }
  2054.  
  2055.     // }}}
  2056.     // {{{ getListOf()
  2057.  
  2058.     /**
  2059.      * Lists internal database information
  2060.      *
  2061.      * @param string $type  type of information being sought.
  2062.      *                       Common items being sought are:
  2063.      *                       tables, databases, users, views, functions
  2064.      *                       Each DBMS's has its own capabilities.
  2065.      *
  2066.      * @return array  an array listing the items sought.
  2067.      *                 A DB DB_Error object on failure.
  2068.      */
  2069.     function getListOf($type)
  2070.     {
  2071.         $sql = $this->getSpecialQuery($type);
  2072.         if ($sql === null) {
  2073.             $this->last_query = '';
  2074.             return $this->raiseError(DB_ERROR_UNSUPPORTED);
  2075.         } elseif (is_int($sql) || DB::isError($sql)) {
  2076.             // Previous error
  2077.             return $this->raiseError($sql);
  2078.         } elseif (is_array($sql)) {
  2079.             // Already the result
  2080.             return $sql;
  2081.         }
  2082.         // Launch this query
  2083.         return $this->getCol($sql);
  2084.     }
  2085.  
  2086.     // }}}
  2087.     // {{{ getSpecialQuery()
  2088.  
  2089.     /**
  2090.      * Obtains the query string needed for listing a given type of objects
  2091.      *
  2092.      * @param string $type  the kind of objects you want to retrieve
  2093.      *
  2094.      * @return string  the SQL query string or null if the driver doesn't
  2095.      *                  support the object type requested
  2096.      *
  2097.      * @access protected
  2098.      * @see DB_common::getListOf()
  2099.      */
  2100.     function getSpecialQuery($type)
  2101.     {
  2102.         return $this->raiseError(DB_ERROR_UNSUPPORTED);
  2103.     }
  2104.  
  2105.     // }}}
  2106.     // {{{ _rtrimArrayValues()
  2107.  
  2108.     /**
  2109.      * Right-trims all strings in an array
  2110.      *
  2111.      * @param array $array  the array to be trimmed (passed by reference)
  2112.      *
  2113.      * @return void
  2114.      *
  2115.      * @access protected
  2116.      */
  2117.     function _rtrimArrayValues(&$array)
  2118.     {
  2119.         foreach ($array as $key => $value) {
  2120.             if (is_string($value)) {
  2121.                 $array[$key] = rtrim($value);
  2122.             }
  2123.         }
  2124.     }
  2125.  
  2126.     // }}}
  2127.     // {{{ _convertNullArrayValuesToEmpty()
  2128.  
  2129.     /**
  2130.      * Converts all null values in an array to empty strings
  2131.      *
  2132.      * @param array  $array  the array to be de-nullified (passed by reference)
  2133.      *
  2134.      * @return void
  2135.      *
  2136.      * @access protected
  2137.      */
  2138.     function _convertNullArrayValuesToEmpty(&$array)
  2139.     {
  2140.         foreach ($array as $key => $value) {
  2141.             if (is_null($value)) {
  2142.                 $array[$key] = '';
  2143.             }
  2144.         }
  2145.     }
  2146.  
  2147.     // }}}
  2148. }
  2149.  
  2150. /*
  2151.  * Local variables:
  2152.  * tab-width: 4
  2153.  * c-basic-offset: 4
  2154.  * End:
  2155.  */
  2156.  
  2157. ?>
  2158.